home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sndhrdw / exidy.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  12KB  |  417 lines

  1. #include "driver.h"
  2. #include "cpu/m6502/m6502.h"
  3. #include "machine/6821pia.h"
  4. #include "sound/hc55516.h"
  5.  
  6. static void *timer;
  7. #define BASE_TIME 1/.894886
  8. #define BASE_FREQ (1789773 * 2)
  9. #define SH6840_FREQ 894886
  10. #define CVSD_CLOCK_FREQ (1000000.0 / 34.0)
  11. #define VOLUME 60
  12.  
  13. int exidy_sample_channels[6];
  14. unsigned int exidy_sh8253_count[3];     /* 8253 Counter */
  15. int exidy_sh8253_clstate[3];            /* which byte to load */
  16. int riot_divider;
  17. int riot_state;
  18.  
  19. #define RIOT_IDLE 0
  20. #define RIOT_COUNTUP 1
  21. #define RIOT_COUNTDOWN 2
  22.  
  23. int mtrap_voice;
  24. int mtrap_count;
  25. int mtrap_vocdata;
  26.  
  27. static signed char exidy_waveform1[16] =
  28. {
  29.     /* square-wave */
  30.     0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F,
  31.     0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F
  32. };
  33.  
  34. int exidy_shdata_latch = 0xFF;
  35. int exidy_mhdata_latch = 0xFF;
  36.  
  37. /* 6532 variables */
  38. static int irq_flag = 0;   /* 6532 interrupt flag register */
  39. static int irq_enable = 0;
  40. static int PA7_irq = 0;  /* IRQ-on-write flag (sound CPU) */
  41.  
  42. /* 6840 variables */
  43. static int sh6840_CR1,sh6840_CR2,sh6840_CR3;
  44. static int sh6840_MSB;
  45. static unsigned int sh6840_timer[3];
  46. static int exidy_sfxvol[3];
  47. static int exidy_sfxctrl;
  48.  
  49. /***************************************************************************
  50.     PIA Interface
  51. ***************************************************************************/
  52.  
  53. static void exidy_irq (int state);
  54.  
  55. /* PIA 0 */
  56. static struct pia6821_interface pia_0_intf =
  57. {
  58.     /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
  59.     /*outputs: A/B,CA/B2       */ pia_1_portb_w, pia_1_porta_w, pia_1_cb1_w, pia_1_ca1_w,
  60.     /*irqs   : A/B             */ 0, 0
  61. };
  62.  
  63. /* PIA 1 */
  64. static struct pia6821_interface pia_1_intf =
  65. {
  66.     /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
  67.     /*outputs: A/B,CA/B2       */ pia_0_portb_w, pia_0_porta_w, pia_0_cb1_w, pia_0_ca1_w,
  68.     /*irqs   : A/B             */ 0, exidy_irq
  69. };
  70.  
  71. /**************************************************************************
  72.     Start/Stop Sound
  73. ***************************************************************************/
  74.  
  75. int exidy_sh_start(const struct MachineSound *msound)
  76. {
  77.     /* Init 8253 */
  78.     exidy_sh8253_clstate[0]=0;
  79.     exidy_sh8253_clstate[1]=0;
  80.     exidy_sh8253_clstate[2]=0;
  81.     exidy_sh8253_count[0]=0;
  82.     exidy_sh8253_count[1]=0;
  83.     exidy_sh8253_count[2]=0;
  84.  
  85.     exidy_sample_channels[0] = mixer_allocate_channel(25);
  86.     exidy_sample_channels[1] = mixer_allocate_channel(25);
  87.     exidy_sample_channels[2] = mixer_allocate_channel(25);
  88.     mixer_set_volume(exidy_sample_channels[0],0);
  89.     mixer_play_sample(exidy_sample_channels[0],(signed char*)exidy_waveform1,16,1000,1);
  90.     mixer_set_volume(exidy_sample_channels[1],0);
  91.     mixer_play_sample(exidy_sample_channels[1],(signed char*)exidy_waveform1,16,1000,1);
  92.     mixer_set_volume(exidy_sample_channels[2],0);
  93.     mixer_play_sample(exidy_sample_channels[2],(signed char*)exidy_waveform1,16,1000,1);
  94.  
  95.     /* Init PIA */
  96.     pia_config(0, PIA_STANDARD_ORDERING, &pia_0_intf);
  97.     pia_config(1, PIA_STANDARD_ORDERING, &pia_1_intf);
  98.     pia_reset();
  99.  
  100.     /* Init 6532 */
  101.     timer=0;
  102.     riot_divider = 1;
  103.     riot_state = RIOT_IDLE;
  104.  
  105.     /* Init 6840 */
  106.     sh6840_CR1 = sh6840_CR2 = sh6840_CR3 = 0;
  107.     sh6840_MSB = 0;
  108.     sh6840_timer[0] = sh6840_timer[1] = sh6840_timer[2] = 0;
  109.     exidy_sfxvol[0] = exidy_sfxvol[1] = exidy_sfxvol[2] = 0;
  110.     exidy_sample_channels[3] = mixer_allocate_channel(25);
  111.     exidy_sample_channels[4] = mixer_allocate_channel(25);
  112.     exidy_sample_channels[5] = mixer_allocate_channel(25);
  113.     mixer_set_volume(exidy_sample_channels[3],0);
  114.     mixer_play_sample(exidy_sample_channels[3],(signed char*)exidy_waveform1,16,1000,1);
  115.     mixer_set_volume(exidy_sample_channels[4],0);
  116.     mixer_play_sample(exidy_sample_channels[4],(signed char*)exidy_waveform1,16,1000,1);
  117.     mixer_set_volume(exidy_sample_channels[5],0);
  118.     mixer_play_sample(exidy_sample_channels[5],(signed char*)exidy_waveform1,16,1000,1);
  119.  
  120.     /* Setup Mousetrap Voice */
  121.     mtrap_voice = 0xff;
  122.     mtrap_count = 0;
  123.     return 0;
  124. }
  125.  
  126. void exidy_sh_stop(void)
  127. {
  128.     mixer_stop_sample(exidy_sample_channels[0]);
  129.     mixer_stop_sample(exidy_sample_channels[1]);
  130.     mixer_stop_sample(exidy_sample_channels[2]);
  131. }
  132.  
  133. /*
  134.  *  PIA callback to generate the interrupt to the main CPU
  135.  */
  136.  
  137. static void exidy_irq (int state)
  138. {
  139.     cpu_set_irq_line (1, 0, state ? ASSERT_LINE : CLEAR_LINE);
  140. }
  141.  
  142. /**************************************************************************
  143.     6532 RIOT
  144. ***************************************************************************/
  145.  
  146. static void riot_interrupt(int parm)
  147. {
  148.     if (riot_state == RIOT_COUNTUP) {
  149.         irq_flag |= 0x80; /* set timer interrupt flag */
  150.         if (irq_enable) cpu_cause_interrupt (1, M6502_INT_IRQ);
  151.         riot_state = RIOT_COUNTDOWN;
  152.         timer = timer_set (TIME_IN_USEC((1*BASE_TIME)*0xFF), 0, riot_interrupt);
  153.     }
  154.     else {
  155.         timer=0;
  156.         riot_state = RIOT_IDLE;
  157.     }
  158. }
  159.  
  160.  
  161. WRITE_HANDLER( exidy_shriot_w )
  162. {
  163.    offset &= 0x7F;
  164.    switch (offset)
  165.    {
  166.    case 0:
  167.         cpu_set_reset_line(2, (data & 0x10) ? CLEAR_LINE : ASSERT_LINE);
  168.         mtrap_voice = data;
  169.         return;
  170.        case 7: /* 0x87 - Enable Interrupt on PA7 Transitions */
  171.         PA7_irq = data;
  172.         return;
  173.     case 0x14:
  174.     case 0x1c:
  175.         irq_enable=offset & 0x08;
  176.         riot_divider = 1;
  177.         if (timer) timer_remove(timer);
  178.         timer = timer_set (TIME_IN_USEC((1*BASE_TIME)*data), 0, riot_interrupt);
  179.         riot_state = RIOT_COUNTUP;
  180.         return;
  181.     case 0x15:
  182.     case 0x1d:
  183.         irq_enable=offset & 0x08;
  184.         riot_divider = 8;
  185.         if (timer) timer_remove(timer);
  186.         timer = timer_set (TIME_IN_USEC((8*BASE_TIME)*data), 0, riot_interrupt);
  187.         riot_state = RIOT_COUNTUP;
  188.         return;
  189.     case 0x16:
  190.     case 0x1e:
  191.         irq_enable=offset & 0x08;
  192.         riot_divider = 64;
  193.         if (timer) timer_remove(timer);
  194.         timer = timer_set (TIME_IN_USEC((64*BASE_TIME)*data), 0, riot_interrupt);
  195.         riot_state = RIOT_COUNTUP;
  196.         return;
  197.     case 0x17:
  198.     case 0x1f:
  199.         irq_enable=offset & 0x08;
  200.         riot_divider = 1024;
  201.         if (timer) timer_remove(timer);
  202.         timer = timer_set (TIME_IN_USEC((1024*BASE_TIME)*data), 0, riot_interrupt);
  203.         riot_state = RIOT_COUNTUP;
  204.         return;
  205.     default:
  206.         logerror("Undeclared RIOT write: %x=%x\n",offset,data);
  207.         return;
  208.     }
  209.     return; /* will never execute this */
  210. }
  211.  
  212.  
  213. READ_HANDLER( exidy_shriot_r )
  214. {
  215.     static int temp;
  216.  
  217.     offset &= 0x07;
  218.     switch (offset)
  219.     {
  220.     case 0x02:
  221.           return (mtrap_voice & 0x80) >> 7;
  222.     case 0x05: /* 0x85 - Read Interrupt Flag Register */
  223.     case 0x07:
  224.         temp = irq_flag;
  225.         irq_flag = 0;   /* Clear int flags */
  226.         return temp;
  227.     case 0x04:
  228.     case 0x06:
  229.         irq_flag = 0;
  230.         if (riot_state == RIOT_COUNTUP) {
  231.             return timer_timeelapsed(timer)/(TIME_IN_USEC((riot_divider*BASE_TIME)));
  232.         }
  233.         else {
  234.             return timer_timeleft(timer)/(TIME_IN_USEC((riot_divider*BASE_TIME)));
  235.         }
  236.     default:
  237.         logerror("Undeclared RIOT read: %x  PC:%x\n",offset,cpu_get_pc());
  238.           return 0xff;
  239.     }
  240.     return 0;
  241. }
  242.  
  243. /**************************************************************************
  244.     8253 Timer
  245. ***************************************************************************/
  246.  
  247. WRITE_HANDLER( exidy_sh8253_w )
  248. {
  249.     int i,c;
  250.     long f;
  251.  
  252.  
  253.     i = offset & 0x03;
  254.     if (i == 0x03) {
  255.         c = (data & 0xc0) >> 6;
  256.         if (exidy_sh8253_count[c])
  257.             f = BASE_FREQ / exidy_sh8253_count[c];
  258.         else
  259.             f = 1;
  260.  
  261.         if ((data & 0x0E) == 0) {
  262.             mixer_set_sample_frequency(exidy_sample_channels[c],f);
  263.             mixer_set_volume(exidy_sample_channels[c],0);
  264.         }
  265.         else {
  266.             mixer_set_sample_frequency(exidy_sample_channels[c],f);
  267.             mixer_set_volume(exidy_sample_channels[c],VOLUME);
  268.         }
  269.     }
  270.  
  271.     if (i < 0x03)
  272.     {
  273.         if (!exidy_sh8253_clstate[i])
  274.         {
  275.             exidy_sh8253_clstate[i]=1;
  276.             exidy_sh8253_count[i] &= 0xFF00;
  277.             exidy_sh8253_count[i] |= (data & 0xFF);
  278.         }
  279.         else
  280.         {
  281.             exidy_sh8253_clstate[i]=0;
  282.             exidy_sh8253_count[i] &= 0x00FF;
  283.             exidy_sh8253_count[i] |= ((data & 0xFF) << 8);
  284.             if (!exidy_sh8253_count[i])
  285.                 f = 1;
  286.             else
  287.                 f = BASE_FREQ / exidy_sh8253_count[i];
  288.             mixer_set_sample_frequency(exidy_sample_channels[i],f);
  289.         }
  290.     }
  291.  
  292.  
  293. }
  294.  
  295. READ_HANDLER( exidy_sh8253_r )
  296. {
  297.     logerror("8253(R): %x\n",offset);
  298.     return 0;
  299. }
  300.  
  301. /**************************************************************************
  302.     6840 Timer
  303. ***************************************************************************/
  304.  
  305. READ_HANDLER( exidy_sh6840_r ) {
  306.     logerror("6840R %x\n",offset);
  307.     return 0;
  308. }
  309.  
  310. WRITE_HANDLER( exidy_sh6840_w ) {
  311.         offset &= 0x07;
  312.     switch (offset) {
  313.         case 0:
  314.             if (sh6840_CR2 & 0x01) {
  315.                 sh6840_CR1 = data;
  316.                 if ((data & 0x38) == 0) mixer_set_volume(exidy_sample_channels[3],0);
  317.             }
  318.             else {
  319.                 sh6840_CR3 = data;
  320.                 if ((data & 0x38) == 0) mixer_set_volume(exidy_sample_channels[5],0);
  321.             }
  322.             break;
  323.  
  324.         case 1:
  325.             sh6840_CR2 = data;
  326.             if ((data & 0x38) == 0) mixer_set_volume(exidy_sample_channels[4],0);
  327.             break;
  328.         case 2:
  329.         case 4:
  330.         case 6:
  331.             sh6840_MSB = data;
  332.             break;
  333.         case 3:
  334.             sh6840_timer[0] = (sh6840_MSB << 8) | (data & 0xFF);
  335.             if (sh6840_timer[0] != 0 && !(exidy_sfxctrl & 0x02))
  336.             {
  337.                 mixer_set_sample_frequency(exidy_sample_channels[3],SH6840_FREQ/sh6840_timer[0]);
  338.                 mixer_set_volume(exidy_sample_channels[3],exidy_sfxvol[0]*VOLUME/7);
  339.             }
  340.             else
  341.                 mixer_set_volume(exidy_sample_channels[3],0);
  342.             break;
  343.         case 5:
  344.             sh6840_timer[1] = (sh6840_MSB << 8) | (data & 0xFF);
  345.             if (sh6840_timer[1] != 0)
  346.             {
  347.                 mixer_set_sample_frequency(exidy_sample_channels[4],SH6840_FREQ/sh6840_timer[1]);
  348.                 mixer_set_volume(exidy_sample_channels[4],exidy_sfxvol[1]*VOLUME/7);
  349.             }
  350.             else
  351.                 mixer_set_volume(exidy_sample_channels[4],0);
  352.             break;
  353.         case 7:
  354.             sh6840_timer[2] = (sh6840_MSB << 8) | (data & 0xFF);
  355.             if (sh6840_timer[2] != 0)
  356.             {
  357.                 mixer_set_sample_frequency(exidy_sample_channels[5],SH6840_FREQ/sh6840_timer[2]);
  358.                 mixer_set_volume(exidy_sample_channels[5],exidy_sfxvol[2]*VOLUME/7);
  359.             }
  360.             else
  361.                 mixer_set_volume(exidy_sample_channels[5],0);
  362.             break;
  363.     }
  364. }
  365.  
  366. /**************************************************************************
  367.     Special Sound FX Control
  368. ***************************************************************************/
  369.  
  370. WRITE_HANDLER( exidy_sfxctrl_w ) {
  371.     switch (offset & 0x03) {
  372.     case 0:
  373.         exidy_sfxctrl = data;
  374.         if (!(data & 0x02)) mixer_set_volume(exidy_sample_channels[3],0);
  375.         break;
  376.     case 1:
  377.     case 2:
  378.     case 3:
  379.         exidy_sfxvol[offset - 1] = (data & 0x07);
  380.         break;
  381.     }
  382. }
  383.  
  384. /**************************************************************************
  385.     Mousetrap Digital Sound
  386. ***************************************************************************/
  387.  
  388.  
  389. WRITE_HANDLER( mtrap_voiceio_w ) {
  390.     if (!(offset & 0x10)) {
  391.         hc55516_digit_clock_clear_w(0,data);
  392.         hc55516_clock_set_w(0,data);
  393.     }
  394.     if (!(offset & 0x20)) {
  395.         mtrap_voice &= 0x7F;
  396.         mtrap_voice |= ((data & 0x01) << 7);
  397.     }
  398. }
  399.  
  400. READ_HANDLER( mtrap_voiceio_r ) {
  401.     int data=0;
  402.  
  403.     if (!(offset & 0x80)) {
  404.        data = (mtrap_voice & 0x06) >> 1;
  405.        data |= (mtrap_voice & 0x01) << 2;
  406.        data |= (mtrap_voice & 0x08);
  407.        return data;
  408.     }
  409.     if (!(offset & 0x40)) {
  410.         int clock_pulse = (int)(timer_get_time() * (2.0 * CVSD_CLOCK_FREQ));
  411.         return (clock_pulse & 1) << 7;
  412.     }
  413.     return 0;
  414. }
  415.  
  416.  
  417.